package com.jiawa.train.common.validator;

import com.jiawa.train.common.validation.ValidEnum;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

@Component
public class EnumValidator implements ConstraintValidator<ValidEnum, String> {

    private Class<? extends Enum<?>> enumClass;
    private String property;

    @Override
    public void initialize(ValidEnum annotation) {
        this.enumClass = annotation.enumClass();
        this.property = annotation.property();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        // 如果值为空，不进行校验（由@NotBlank等注解处理）
        if (value == null || value.trim().isEmpty()) {
            return true;
        }

        try {
            // 获取枚举类的所有常量
            Enum<?>[] enumConstants = enumClass.getEnumConstants();

            // 获取getter方法
            String methodName = "get" + property.substring(0, 1).toUpperCase() + property.substring(1);
            Method method = null;

            try {
                method = enumClass.getMethod(methodName);
            } catch (NoSuchMethodException e) {
                // 如果没有getter方法，尝试直接访问字段
                try {
                    enumClass.getField(property);
                    methodName = property;
                    method = enumClass.getMethod(methodName);
                } catch (NoSuchFieldException | NoSuchMethodException ex) {
                    // 如果还是找不到，使用name()方法
                    method = Enum.class.getMethod("name");
                }
            }

            // 遍历枚举常量，检查是否有匹配的值
            for (Enum<?> enumConstant : enumConstants) {
                Object enumValue = method.invoke(enumConstant);
                if (value.equals(enumValue != null ? enumValue.toString() : null)) {
                    return true;
                }
            }
        } catch (Exception e) {
            return false;
        }

        return false;
    }
}
